package com.pinapel.aixml.models.xml.dom.xsd;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class SaxPathHandler extends DefaultHandler {

    // map of all encountered tags and their running count
    private Map<String, Integer> tagCount;
    // keep track of the succession of elements
    private Stack<String> tags;

    // set to the tag name of the recently closed tag
    String lastClosedTag;
    
    /** Mapping from level into tags ready for cleaning. **/
    private Map<Integer, List<String>> mCleanList;
    private int mCurrentLevel;


    /**
     * Construct the XPath expression
     */
    public String getCurrentXPath() {
        String str = "/";
        boolean first = true;
        for (String tag : tags) {
            if (first)
                str = str + tag;
            else
                str = str + "/" + tag;
            str += "["+tagCount.get(tag)+"]";
            first = false;
        }
        return str;
    }

    @Override
    public void startDocument() throws SAXException {
        tags = new Stack();
        tagCount = new HashMap<String, Integer>();
        mCleanList = new HashMap<Integer,List<String>>();
        mCurrentLevel = 0;
    }

    @Override
    public void startElement (String namespaceURI, String localName, String qName, Attributes atts)
        throws SAXException
    {
        boolean isRepeatElement = false;
        mCurrentLevel++;

        if (tagCount.get(localName) == null) {
            tagCount.put(localName, 1);
            List<String> l = mCleanList.get(mCurrentLevel);       
            if(l==null) {
            	l = new ArrayList<String>();
            }
            l.add(localName);
            mCleanList.put(mCurrentLevel, l);
        } else {
            tagCount.put(localName, 1 + tagCount.get(localName));
        }

        if (lastClosedTag != null) {
            // an element was recently closed ...
            if (lastClosedTag.equals(localName)) {
                // ... and it's the same as the current one
                isRepeatElement = true;
            } else {
                // ... but it's different from the current one, so discard it
                tags.pop();
            }
        }

        // if it's not the same element, add the new element and zero count to list
        if (! isRepeatElement) {
            tags.push(localName);
        }

//        System.out.println(getCurrentXPath());
        lastClosedTag = null;
    }

    @Override
    public void endElement (String uri, String localName, String qName) throws SAXException {
        // if two tags are closed in succession (without an intermediate opening tag),
        // then the information about the deeper nested one is discarded
        if (lastClosedTag != null) {
            tags.pop();
        }
        lastClosedTag = localName;
        List<String> tagList = mCleanList.get(mCurrentLevel+1);
        if(tagList!=null) {
	        for(String t:tagList) {
	        	// Clean the tagCount
	        	tagCount.remove(t);
	        }
        }
        mCurrentLevel--;
    }
    
}